<?php

namespace App\V3\V3_2_7\Services;

use App\Services\CommonService;
use App\Services\MessageService;
use App\V3\V3_2_7\Models\LogOutStorageModel;
use App\V3\V3_2_7\Models\MaterielTypeModel;
use App\V3\V3_2_7\Models\OperMainAccountModel;
use App\V3\V3_2_7\Models\StorageBatchModel;
use App\V3\V3_2_7\Models\StorageManageModel;
use App\V3\V3_2_7\Models\StorageModel;
use App\V3\V3_2_7\Models\StorageShelfLocationModel;
use App\V3\V3_2_7\Models\StorageShelfModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ScanCodeOutStorageService
{
    /**
     *扫码出库-基地
     * Author: zlf
     * Created at 2024/6/28 16:03
     * @param $data
     * @return array|null
     */
    public static function scanCodeOutStorage($data): ?array
    {
        $result = [];
        //仓库扫码出库
        if (!empty($data['storage_id'])) {
            $result = self::storageCodeOutStorage($data);
        }
        //货架扫码出库
        if (!empty($data['shelf_id'])) {
            $result = self::shelfCodeOutStorage($data);
        }
        //库位扫码出库
        if (!empty($data['location_id'])) {
            $result = self::locationCodeOutStorage($data);
        }
        return $result;
    }

    /**
     *仓库扫码出库
     * Author: zlf
     * Created at 2024/6/28 15:51
     * @param $data
     * @return array|null
     */
    public static function storageCodeOutStorage($data, $operType = 0): ?array
    {
        if (!$operType)
            DB::beginTransaction();
        try {
            $goodsInfo = MaterielTypeModel::query()
                ->where([
                    'id' => $data['type_id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0,
                ])->first();
            if (empty($goodsInfo))
                throw new \RuntimeException("无商品信息！");
            $storageInfo = StorageModel::query()->where([
                'id' => $data['storage_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($storageInfo))
                throw new \RuntimeException("无仓库信息！");
            $manageList = StorageManageModel::query()
                ->where([
                    'delete_flag' => 0,
                    'type_id' => $data['type_id'],
                    'storage_id' => $data['storage_id'],
                    'main_id' => $data['main_id'],
                    ['in_storage_num', '>', 0]
                ])->get();

            if (!empty($manageList)) {
                $manageList = $manageList->toArray();
                self::multiShelfLocationHandle($goodsInfo, $storageInfo, $manageList, $data);
            } else {
                if (!OperMainAccountModel::query()
                    ->where([
                        'main_id' => $data['main_id'],
                        'delete_flag' => 0
                    ])->exists()) {
                    throw new \RuntimeException("商品：" . $goodsInfo['materiel_name'] . " 库存不足，无法出库！");
                }
                self::defShelfLocationHandle($goodsInfo, $storageInfo, $data);
            }
            if (!$operType)
                DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            if (!$operType)
                DB::rollBack();
            Log::debug('仓库-扫码出库（孵化）异常：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     *货架扫码出库
     * Author: zlf
     * Created at 2024/6/28 15:47
     * @param $data
     * @return array
     */
    public static function shelfCodeOutStorage($data, $operType = 0): ?array
    {
        if (!$operType)
            DB::beginTransaction();
        try {
            $goodsInfo = MaterielTypeModel::query()->where([
                'id' => $data['type_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($goodsInfo))
                throw new \RuntimeException("无商品信息！");
            $shelfInfo = StorageShelfModel::query()
                ->where([
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'id' => $data['shelf_id']
                ])->first();
            if (empty($shelfInfo))
                throw new \RuntimeException("无货架信息！");
            $storageInfo = StorageModel::query()->where([
                'id' => $shelfInfo['storage_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($storageInfo))
                throw new \RuntimeException("无仓库信息！");
            $manageList = StorageManageModel::query()
                ->where([
                    'delete_flag' => 0,
                    'type_id' => $data['type_id'],
                    'storage_id' => $shelfInfo['storage_id'],
                    'main_id' => $data['main_id'],
                    ['in_storage_num', '>', 0],
                    'shelf_id' => $shelfInfo['id']
                ])->get();

            if (!empty($manageList)) {
                $manageList = $manageList->toArray();
                self::multiShelfLocationHandle($goodsInfo, $storageInfo, $manageList, $data);
            } else {
                if (!OperMainAccountModel::query()
                    ->where([
                        'main_id' => $data['main_id'],
                        'delete_flag' => 0
                    ])->exists()) {
                    throw new \RuntimeException("商品：" . $goodsInfo['materiel_name'] . " 库存不足，无法出库！");
                }
                self::defShelfLocationHandle($goodsInfo, $storageInfo, $data);
            }
            if (!$operType)
                DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            if (!$operType)
                DB::rollBack();
            Log::debug('货架-扫码出库（孵化）异常：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }

    }

    /**
     *库位打码出库
     * Author: zlf
     * Created at 2024/6/28 16:05
     * @param $data
     * @return array
     */
    public static function locationCodeOutStorage($data, $operType = 0): ?array
    {
        if (!$operType)
            DB::beginTransaction();
        try {
            $goodsInfo = MaterielTypeModel::query()->where([
                'id' => $data['type_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($goodsInfo))
                throw new \RuntimeException("无商品信息！");
            $locationInfo = StorageShelfLocationModel::query()
                ->where([
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'id' => $data['location_id'],
                ])->first();
            if (empty($locationInfo))
                throw new \RuntimeException("无库位信息！");
            $storageInfo = StorageModel::query()->where([
                'id' => $locationInfo['storage_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($storageInfo))
                throw new \RuntimeException("无仓库信息！");
            $shelfInfo = StorageShelfModel::query()
                ->where([
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'id' => $locationInfo['shelf_id']
                ])->first();
            if (empty($shelfInfo))
                throw new \RuntimeException("无货架信息！");
            $manageInfo = StorageManageModel::query()->where([
                'type_id' => $data['type_id'],
                'storage_id' => $storageInfo['id'],
                'shelf_id' => $shelfInfo['id'],
                'location_id' => $locationInfo['id'],
                'delete_flag' => 0
            ])->first();
            if (!OperMainAccountModel::query()
                ->where([
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0
                ])->exists()) {
                if (empty($manageInfo) || $manageInfo['in_storage_num'] < $data['num']) {
                    throw new \RuntimeException("商品：" . $goodsInfo['materiel_name'] . " 库存不足，无法出库！");
                }
            }
            self::outStorage($goodsInfo, $storageInfo, $manageInfo, $data);
            if (!$operType)
                DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            if (!$operType)
                DB::rollBack();
            Log::debug('扫码出库（孵化）异常：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //多个库存
    private static function multiShelfLocationHandle($goodsInfo, $storageInfo, $manageList, $data): void
    {
        $totalNum = 0;
        foreach ($manageList as $lVal) {
            $totalNum += $lVal['in_storage_num'];
        }
        if (!OperMainAccountModel::query()
            ->where([
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->exists()) {
            if ($totalNum < $data['num']) {
                throw new \RuntimeException("商品：" . $goodsInfo['materiel_name'] . " 库存不足，无法出库！");
            }
        }

        foreach ($manageList as $lVal) {
            //每个库位库存大于操作数量
            if ($lVal['in_storage_num'] >= $data['num'] && $data['num'] > 0) {
                self::outStorage($goodsInfo, $storageInfo, $lVal, $data);
                $data['num'] = 0;
                break;
            } else {
                if ($data['num'] > 0) {
                    $data['num'] -= $lVal['in_storage_num'];
                    if ($data['num'] >= 0) {
                        $data['sub_num'] = $lVal['in_storage_num'];
                        self::outStorage($goodsInfo, $storageInfo, $lVal, $data);
                    }
                }
            }
        }
        unset($data['sub_num']);
        //dump_dug($data['num']);
        //剩余的出库数量添加到默认货架库位
        if ($data['num'] > 0) {
            self::defShelfLocationHandle($goodsInfo, $storageInfo, $data);
        }
    }

    //默认货架库位出库前处理
    private static function defShelfLocationHandle($goodsInfo, $storageInfo, $data): void
    {
        $shlefInfo = StorageShelfModel::query()
            ->where([
                'status' => 1,
                'storage_id' => $storageInfo['id'],
                'main_id' => $data['main_id'],
                'shelf_type' => 1
            ])->first();
        if (empty($shlefInfo))
            throw new \RuntimeException('无货架信息！');
        $locationInfo = StorageShelfLocationModel::query()
            ->where([
                'status' => 1,
                'location_type' => 1,
                'storage_id' => $storageInfo['id'],
                'main_id' => $data['main_id'],
                'shelf_id' => $shlefInfo['id'],
            ])->first();
        if (empty($locationInfo))
            throw new \RuntimeException('无库位信息！');
        $manageInfo = StorageManageModel::query()
            ->where([
                'delete_flag' => 0,
                'storage_id' => $storageInfo['id'],
                'main_id' => $data['main_id'],
                'shelf_id' => $shlefInfo['id'],
                'location_id' => $locationInfo['id'],
            ])->first();
        if (empty($manageInfo))
            throw new \RuntimeException('无库存信息！');
        self::outStorage($goodsInfo, $storageInfo, $manageInfo, $data);
    }

    //出库
    private static function outStorage($goodsInfo, $storageInfo, $manageInfo, $data): void
    {
        $data['num'] = !empty($data['sub_num']) ? $data['sub_num'] : $data['num'];
        $batchInfo = StorageBatchModel::query()->where([
            'main_id' => $data['main_id'],
            'storage_manage_id' => $manageInfo['id']
        ])->first();
        if (!empty($batchInfo))
            $batchInfo->decrement('batch_left_num', $data['num']);

        //出库操作记录
        $logId = LogOutStorageModel::query()->insertGetId([
            'type' => !empty($data['type']) ? $data['type'] : 4,
            'storage_batch_id' => $batchInfo['id'] ?? '',
            'batch_no' => $batchInfo['batch_no'] ?? '',
            'storage_id' => $storageInfo['id'],
            'storage_name' => $storageInfo['storage_name'],
            'storage_address' => $storageInfo['storage_address'],
            'curr_storage_manage_id' => $manageInfo['id'],
            'materiel_class_id' => $goodsInfo['materiel_class_id'],
            'materiel_type_id' => $goodsInfo['id'],
            'materiel_name' => $goodsInfo['materiel_name'],
            'type_name' => $goodsInfo['type_name'],
            'materiel_no' => $goodsInfo['materiel_no'],
            'operate_num' => $data['num'],
            'last_storage_num' => $manageInfo['in_storage_num'],
            'next_storage_num' => $manageInfo['in_storage_num'] - $data['num'],
            'sell_price' => $goodsInfo['selling_price'],
            'materiel_mean_cost' => $goodsInfo['cost'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            'shelf_id' => $manageInfo['shelf_id'],
            'location_id' => $manageInfo['location_id'],
            'out_storage_time' => $data['time'],
            'code_allocate_no' => !empty($data['code_allocate_no']) ? $data['code_allocate_no'] : '',
            'all_id_type' => !empty($data['all_id_type']) ? $data['all_id_type'] : 0,
            'created_at' => $data['time'],
            'label_id' => $data['label_id'] ?? '',
        ]);
        MessageService::sendAlertSms(
            $goodsInfo['materiel_name'],
            $goodsInfo['type_name'],
            $manageInfo['in_storage_num'] - $data['num'],
            $manageInfo['alert_num'],
            $data,
            $manageInfo['storage_id'],
            $manageInfo['storage_name'],
            $data['num']
        );
        MessageService::sendShortSms(
            $goodsInfo['materiel_name'],
            $goodsInfo['type_name'],
            $manageInfo['in_storage_num'] - $data['num'],
            $data,
            $manageInfo['storage_name'],
            $manageInfo['storage_id'],
        );
        MessageService::sendOutSms(
            $goodsInfo['materiel_name'],
            $goodsInfo['type_name'],
            $manageInfo['in_storage_num'] - $data['num'],
            $manageInfo['storage_name'],
            $data['num'],
            $data,
            $manageInfo['storage_id'],
            $manageInfo['alert_num'],
            $logId
        );
        StorageManageModel::query()->where([
            'main_id' => $data['main_id'],
            'id' => $manageInfo['id']
        ])->decrement('in_storage_num', $data['num']);
        CommonService::cancelAlertFlag($data['main_id']);
        $logData = '商品名称：' . $goodsInfo['materiel_name'] .
            '出库数量 ' . $data['num'] . ',仓库名：' . $storageInfo['storage_name'];
        CommonService::operateResult($data['user_id'], $data['time'], $data, $logData);
    }
}
